`timescale 1ns / 1ps
/*
 * Copyright (c) 2020-2021, SERI Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-10-29     Lyons        first version
 */

module pa_core_itcm (
    clk_i,                      // system clock
    rst_n_i,                    // system reset

    data_addr_i,                // d-data address
    data_data_i,                // d-data data
    data_data_o,                // d-data data
    data_we_i,                  // d-data write enable

    inst_addr_i,                // i-data address
    inst_data_o                 // i-data data
    );

`include "../pa_chip_param.v"

input                           clk_i;
input                           rst_n_i;

input  [`ADDR_BUS_WIDTH-1:0]    data_addr_i;
input  [`DATA_BUS_WIDTH-1:0]    data_data_i;
output [`DATA_BUS_WIDTH-1:0]    data_data_o;
input                           data_we_i;

input  [`ADDR_BUS_WIDTH-1:0]    inst_addr_i;
output [`DATA_BUS_WIDTH-1:0]    inst_data_o;

wire                            clk_i;
wire                            rst_n_i;

wire [`ADDR_BUS_WIDTH-1:0]      data_addr_i;
wire [`DATA_BUS_WIDTH-1:0]      data_data_i;
wire [`DATA_BUS_WIDTH-1:0]      data_data_o;
wire                            data_we_i;

wire [`ADDR_BUS_WIDTH-1:0]      inst_addr_i;
wire [`DATA_BUS_WIDTH-1:0]      inst_data_o;


`ifdef ROM_MODE_BRAM

blk_mem_itcm u_blk_mem_itcm (
    .clka                       (clk_i),
    .wea                        ({4{`INVALID}}),
    .addra                      (inst_addr_i),
    .dina                       ({32'hffff_ffff}),
    .douta                      (inst_data_o),

    .clkb                       (clk_i),
    .web                        ({4{data_we_i}}),
    .addrb                      (data_addr_i),
    .dinb                       (data_data_i),
    .doutb                      (data_data_o)
);

`else

reg  [`DATA_BUS_WIDTH-1:0]      _rom[0:`ROM_SIZE*1024-1];

wire [`ADDR_BUS_WIDTH-1:0]      data_addr;
wire [`ADDR_BUS_WIDTH-1:0]      inst_addr;

assign data_addr[`ADDR_BUS_WIDTH-1:0] = {2'b0, data_addr_i[31:2]};
assign inst_addr[`ADDR_BUS_WIDTH-1:0] = {2'b0, inst_addr_i[31:2]};

reg  [`DATA_BUS_WIDTH-1:0]      _data_data;
reg  [`DATA_BUS_WIDTH-1:0]      _inst_data;

`ifdef TEST_ISA

// Only jtag can write to itcm
// When the isa test is performed, the write operation is temporarily allowed
always @ (posedge clk_i) begin
    if (data_we_i) begin
        _rom[data_addr] <= data_data_i[`DATA_BUS_WIDTH-1:0];
    end
end

`endif

always @ (posedge clk_i) begin
    if (~rst_n_i) begin
        _data_data[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    end
    else begin
        _data_data[`DATA_BUS_WIDTH-1:0] = _rom[data_addr];
    end
end

always @ (posedge clk_i) begin
    if (~rst_n_i) begin
        _inst_data[`DATA_BUS_WIDTH-1:0] = `ZERO_WORD;
    end
    else begin
        _inst_data[`DATA_BUS_WIDTH-1:0] = _rom[inst_addr];
    end
end

assign data_data_o[`DATA_BUS_WIDTH-1:0] = _data_data[`DATA_BUS_WIDTH-1:0];
assign inst_data_o[`DATA_BUS_WIDTH-1:0] = _inst_data[`DATA_BUS_WIDTH-1:0];

`endif //`ifdef ROM_MODE_BRAM

endmodule